package main.java.com.chankudo.thread;

public class SimpleSyn implements Runnable {
    Caller caller = null;
    Thread thread = null;
    int round = 0;

    public SimpleSyn(Caller caller, int round) {
        this.caller = caller;
        this.round = round;
        thread = new Thread(this);
        thread.start();
    }

    

    public Thread getThread() {
        return thread;
    }



    public void setThread(Thread thread) {
        this.thread = thread;
    }



    @Override
    public void run() {
        for(int i = 0; i<round; i++){
            // 方法二：如果某个类是第三方库提供的，我们无法对这个类的方法签名进行修改。
            // 此时可以将该类的对象放入 synchronized 关键字标记的代码块中 这样同样保证任何时间最多只能有一个线程执行该方法。
            synchronized(caller){
                caller.call(thread.getName());
            }
            
        }
    }

    public static void main(String[] args) {
        Caller caller = new Caller();

        SimpleSyn simpleSyn1 = new SimpleSyn(caller,16);
        SimpleSyn simpleSyn2 = new SimpleSyn(caller,32);
        
        Thread thread1 = simpleSyn1.getThread();
        Thread thread2 = simpleSyn2.getThread();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        String a = String.valueOf(caller.getAcountA());
        String b = String.valueOf(caller.getAcountB());
         
        System.out.println("acountA:"+a+",acountb:"+b);
    }
}

class Caller{
    private int acountA = 0;
    private int acountB = 0;

    // 第一种方式：直接在方法签名上加 synchronized 关键字
    // 从而保证多线程调用该方法时，在任何一个时间段最多只能有一个线程执行该方法。
    //synchronized void call(String threadname){
    void call(String threadname){    
        boolean a2b =  Math.random() > 0.5;
        int tmp = (int)(Math.random()*1000);

        if(!a2b){//如果不是a转b的话，就把值换成负的。
            tmp = -tmp;
        }
        
        acountA -= tmp;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            System.out.println("thread" + threadname + " has been interrupted.");
            //e.printStackTrace();
        }
        acountB += tmp;
    }

    public int getAcountA() {
        return acountA;
    }

    public void setAcountA(int acountA) {
        this.acountA = acountA;
    }

    public int getAcountB() {
        return acountB;
    }

    public void setAcountB(int acountB) {
        this.acountB = acountB;
    }

    
}
